package com.ai.imagetext.service;

import com.ai.imagetext.dto.ImageDTO;
import com.ai.imagetext.dto.TagDTO;
import com.ai.imagetext.entity.Image;
import com.ai.imagetext.entity.ImageTag;
import com.ai.imagetext.entity.Tag;
import com.ai.imagetext.repository.ImageRepository;
import com.ai.imagetext.repository.ImageTagRepository;
import com.ai.imagetext.repository.TagRepository;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.RequestConditionHolder;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SearchService {
    
    private final ImageRepository imageRepository;
    private final TagRepository tagRepository;
    private final ImageTagRepository imageTagRepository;
    private final ImageService imageService;
    
    /**
     * 高级搜索图片
     */
    public Page<ImageDTO> advancedSearchImages(SearchCriteria criteria) {
        log.info("Advanced search with criteria: {}", criteria);
        
        List<Image> allImages = imageRepository.findByIsDeletedFalse(null).getContent();
        List<Image> filteredImages = allImages.stream()
                .filter(image -> matchesSearchCriteria(image, criteria))
                .collect(Collectors.toList());
        
        // 排序
        filteredImages = sortImages(filteredImages, criteria.getSortBy(), criteria.getSortDir());
        
        // 分页
        Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize());
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), filteredImages.size());
        
        List<Image> pageContent = filteredImages.subList(start, end);
        List<ImageDTO> imageDTOs = pageContent.stream()
                .map(this::convertToImageDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(imageDTOs, pageable, filteredImages.size());
    }
    
    /**
     * 根据多个标签筛选图片（支持AND/OR逻辑）
     */
    public Page<ImageDTO> filterImagesByTags(List<String> tagNames, String logic, int page, int size, String sortBy, String sortDir) {
        log.info("Filtering images by tags: {}, logic: {}, userId: {}", tagNames, logic);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Long userId = Long.parseLong(request.getHeader("User"));
        if (tagNames == null || tagNames.isEmpty()) {
            return imageService.getAllImages(page, size, sortBy, sortDir);
        }
        
        Set<Long> imageIds;
        
        if ("OR".equalsIgnoreCase(logic)) {
            // OR逻辑：包含任意一个标签的图片
            imageIds = new HashSet<>();
            for (String tagName : tagNames) {
                List<Long> tagImageIds = imageTagRepository.findImageIdsByTagName(tagName);
                imageIds.addAll(tagImageIds);
            }
        } else {
            // AND逻辑：包含所有标签的图片
            imageIds = new HashSet<>(imageTagRepository.findImageIdsByTagName(tagNames.get(0)));
            for (int i = 1; i < tagNames.size(); i++) {
                List<Long> tagImageIds = imageTagRepository.findImageIdsByTagName(tagNames.get(i));
                imageIds.retainAll(tagImageIds);
            }
        }
        
        if (imageIds.isEmpty()) {
            return Page.empty();
        }
        
        List<Image> images = imageRepository.findAllById(imageIds)
                .stream()
                .filter(image -> !image.getIsDeleted())
                .filter(image -> userId == null || image.getUserId().equals(userId))
                .collect(Collectors.toList());
        
        // 排序
        images = sortImages(images, sortBy, sortDir);
        
        // 分页
        Pageable pageable = PageRequest.of(page, size);
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), images.size());
        
        List<Image> pageContent = images.subList(start, end);
        List<ImageDTO> imageDTOs = pageContent.stream()
                .map(this::convertToImageDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(imageDTOs, pageable, images.size());
    }
    
    /**
     * 获取热门标签（按使用频率排序）
     */
    public List<TagStatistics> getPopularTags(int limit) {
        log.info("Getting popular tags with limit: {}", limit);
        
        List<Object[]> tagUsageStats = imageTagRepository.getTagUsageStatistics();
        
        return tagUsageStats.stream()
                .limit(limit)
                .map(result -> {
                    TagStatistics stats = new TagStatistics();
                    stats.setTagName((String) result[0]);
                    stats.setUsageCount(((Number) result[1]).longValue());
                    return stats;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 获取标签云数据
     */
    public List<TagCloudItem> getTagCloud(int maxTags) {
        log.info("Getting tag cloud with max tags: {}", maxTags);
        
        List<Object[]> tagUsageStats = imageTagRepository.getTagUsageStatistics();
        
        if (tagUsageStats.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 计算权重
        long maxUsage = ((Number) tagUsageStats.get(0)[1]).longValue();
        long minUsage = ((Number) tagUsageStats.get(tagUsageStats.size() - 1)[1]).longValue();
        
        return tagUsageStats.stream()
                .limit(maxTags)
                .map(result -> {
                    String tagName = (String) result[0];
                    long usageCount = ((Number) result[1]).longValue();
                    
                    // 计算权重（1-5级）
                    int weight = calculateTagWeight(usageCount, minUsage, maxUsage);
                    
                    TagCloudItem item = new TagCloudItem();
                    item.setTagName(tagName);
                    item.setUsageCount(usageCount);
                    item.setWeight(weight);
                    return item;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 根据分类获取标签
     */
    public Map<String, List<TagDTO>> getTagsByCategory() {
        log.info("Getting tags grouped by category");
        
        List<Tag> allTags = tagRepository.findByIsDeletedFalseOrderByUsageCountDesc();
        
        return allTags.stream()
                .map(this::convertToTagDTO)
                .collect(Collectors.groupingBy(
                        tag -> tag.getCategory() != null ? tag.getCategory() : "uncategorized"
                ));
    }
    
    /**
     * 智能关键词搜索
     */
    public Page<ImageDTO> intelligentKeywordSearch(String keyword, int page, int size, String sortBy, String sortDir) {
        log.info("Intelligent keyword search for: {}", keyword);
        
        if (keyword == null || keyword.trim().isEmpty()) {
            return imageService.getAllImages(page, size, sortBy, sortDir);
        }
        
        List<Image> allImages = imageRepository.findByIsDeletedFalse(null).getContent();
        List<SearchResult> searchResults = new ArrayList<>();
        
        String normalizedKeyword = keyword.toLowerCase().trim();
        String[] keywords = normalizedKeyword.split("\\s+");
        
        for (Image image : allImages) {
            SearchResult result = calculateRelevanceScore(image, normalizedKeyword, keywords);
            if (result.getRelevanceScore() > 0) {
                searchResults.add(result);
            }
        }
        
        // 按相关性排序
        searchResults.sort((a, b) -> Double.compare(b.getRelevanceScore(), a.getRelevanceScore()));
        
        // 分页
        Pageable pageable = PageRequest.of(page, size);
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), searchResults.size());
        
        List<SearchResult> pageContent = searchResults.subList(start, end);
        List<ImageDTO> imageDTOs = pageContent.stream()
                .map(result -> {
                    ImageDTO dto = convertToImageDTO(result.getImage());
                    if (dto != null) {
                        dto.setRelevanceScore(result.getRelevanceScore());
                        dto.setHighlights(result.getHighlights());
                    }
                    return dto;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        
        return new PageImpl<>(imageDTOs, pageable, searchResults.size());
    }
    
    /**
     * 计算相关性评分
     */
    private SearchResult calculateRelevanceScore(Image image, String normalizedKeyword, String[] keywords) {
        SearchResult result = new SearchResult();
        result.setImage(image);
        
        double totalScore = 0.0;
        List<String> highlights = new ArrayList<>();
        
        // 图片名称匹配（权重：3.0）
        String imageName = image.getName().toLowerCase();
        double nameScore = calculateTextScore(imageName, normalizedKeyword, keywords);
        if (nameScore > 0) {
            totalScore += nameScore * 3.0;
            highlights.add("name:" + highlightText(image.getName(), keywords));
        }
        
        // 图片描述匹配（权重：2.0）
        if (image.getDescription() != null) {
            String description = image.getDescription().toLowerCase();
            double descScore = calculateTextScore(description, normalizedKeyword, keywords);
            if (descScore > 0) {
                totalScore += descScore * 2.0;
                highlights.add("description:" + highlightText(image.getDescription(), keywords));
            }
        }
        
        // 标签匹配（权重：2.5）
        List<String> imageTags = imageTagRepository.findTagNamesByImageId(image.getId());
        for (String tag : imageTags) {
            String tagLower = tag.toLowerCase();
            double tagScore = calculateTextScore(tagLower, normalizedKeyword, keywords);
            if (tagScore > 0) {
                totalScore += tagScore * 2.5;
                highlights.add("tag:" + highlightText(tag, keywords));
            }
        }
        
        // 文案内容匹配（权重：1.5）
        // 这里可以扩展搜索文案内容
        
        result.setRelevanceScore(totalScore);
        result.setHighlights(highlights);
        
        return result;
    }
    
    /**
     * 计算文本匹配分数
     */
    private double calculateTextScore(String text, String normalizedKeyword, String[] keywords) {
        if (text == null || text.isEmpty()) return 0.0;
        
        double score = 0.0;
        
        // 完全匹配（最高分）
        if (text.equals(normalizedKeyword)) {
            score += 10.0;
        }
        
        // 包含完整关键词
        if (text.contains(normalizedKeyword)) {
            score += 5.0;
        }
        
        // 关键词开头匹配
        if (text.startsWith(normalizedKeyword)) {
            score += 3.0;
        }
        
        // 分词匹配
        for (String keyword : keywords) {
            if (keyword.length() > 1) { // 忽略单字符
                if (text.contains(keyword)) {
                    score += 2.0;
                }
                if (text.startsWith(keyword)) {
                    score += 1.0;
                }
            }
        }
        
        // 模糊匹配（编辑距离）
        if (score == 0.0) {
            double similarity = calculateSimilarity(text, normalizedKeyword);
            if (similarity > 0.7) {
                score += similarity;
            }
        }
        
        return score;
    }
    
    /**
     * 计算字符串相似度（简化版）
     */
    private double calculateSimilarity(String s1, String s2) {
        if (s1 == null || s2 == null) return 0.0;
        if (s1.equals(s2)) return 1.0;
        
        int maxLen = Math.max(s1.length(), s2.length());
        if (maxLen == 0) return 1.0;
        
        int editDistance = calculateEditDistance(s1, s2);
        return 1.0 - (double) editDistance / maxLen;
    }
    
    /**
     * 计算编辑距离
     */
    private int calculateEditDistance(String s1, String s2) {
        int m = s1.length();
        int n = s2.length();
        
        int[][] dp = new int[m + 1][n + 1];
        
        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;
        }
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
                }
            }
        }
        
        return dp[m][n];
    }
    
    /**
     * 高亮显示匹配文本
     */
    private String highlightText(String text, String[] keywords) {
        if (text == null || keywords == null) return text;
        
        String result = text;
        for (String keyword : keywords) {
            if (keyword.length() > 1) {
                // 使用HTML标记高亮（前端可以根据需要处理）
                result = result.replaceAll("(?i)" + keyword, "<mark>$0</mark>");
            }
        }
        return result;
    }
    
    /**
     * 搜索历史记录
     */
    public void recordSearchHistory(String keyword, String userId) {
        log.info("Recording search history: keyword={}, userId={}", keyword, userId);
        // 这里可以实现搜索历史记录功能
        // 暂时只记录日志，后续可以扩展到数据库
    }
    
    /**
     * 获取热门搜索词
     */
    public List<String> getHotSearchKeywords(int limit) {
        log.info("Getting hot search keywords with limit: {}", limit);
        
        // 这里可以基于搜索历史统计热门关键词
        // 暂时返回一些示例数据
        List<String> hotKeywords = Arrays.asList(
            "美食", "风景", "人物", "产品", "动物", 
            "建筑", "花朵", "汽车", "科技", "艺术"
        );
        
        return hotKeywords.stream().limit(limit).collect(Collectors.toList());
    }
    
    /**
     * 搜索建议（自动完成）
     */
    public List<SearchSuggestion> getSearchSuggestions(String query, int limit) {
        log.info("Getting search suggestions for query: {}", query);
        
        List<SearchSuggestion> suggestions = new ArrayList<>();
        
        // 标签建议
        List<Tag> matchingTags = tagRepository.findByNameContainingAndIsDeletedFalse(query);
        for (Tag tag : matchingTags) {
            if (suggestions.size() >= limit) break;
            
            SearchSuggestion suggestion = new SearchSuggestion();
            suggestion.setText(tag.getName());
            suggestion.setType("tag");
            suggestion.setUsageCount(tag.getUsageCount());
            suggestions.add(suggestion);
        }
        
        // 图片名称建议
        if (suggestions.size() < limit) {
            List<Image> matchingImages = imageRepository.findByIsDeletedFalse(null).getContent()
                    .stream()
                    .filter(image -> image.getName().toLowerCase().contains(query.toLowerCase()) ||
                                   (image.getDescription() != null && image.getDescription().toLowerCase().contains(query.toLowerCase())))
                    .limit(limit - suggestions.size())
                    .collect(Collectors.toList());
            
            for (Image image : matchingImages) {
                SearchSuggestion suggestion = new SearchSuggestion();
                suggestion.setText(image.getName());
                suggestion.setType("image");
                suggestion.setUsageCount(image.getUsageCount());
                suggestions.add(suggestion);
            }
        }
        
        // 按使用频率排序
        suggestions.sort((a, b) -> Integer.compare(b.getUsageCount(), a.getUsageCount()));
        
        return suggestions.stream().limit(limit).collect(Collectors.toList());
    }
    
    /**
     * 获取相关标签推荐
     */
    public List<String> getRelatedTags(String tagName, int limit) {
        log.info("Getting related tags for: {}", tagName);
        
        // 获取包含该标签的图片
        List<Long> imageIds = imageTagRepository.findImageIdsByTagName(tagName);
        
        if (imageIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 统计这些图片中其他标签的出现频率
        Map<String, Long> tagFrequency = new HashMap<>();
        
        for (Long imageId : imageIds) {
            List<String> imageTags = imageTagRepository.findTagNamesByImageId(imageId);
            for (String tag : imageTags) {
                if (!tag.equals(tagName)) {
                    tagFrequency.put(tag, tagFrequency.getOrDefault(tag, 0L) + 1);
                }
            }
        }
        
        // 按频率排序并返回前N个
        return tagFrequency.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .limit(limit)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
    
    /**
     * 检查图片是否匹配搜索条件
     */
    private boolean matchesSearchCriteria(Image image, SearchCriteria criteria) {
        // 关键词匹配
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Long userId =null;
        if(request.getHeader("User")!=null) {
            userId= Long.parseLong(request.getHeader("User"));
            if(!userId.equals(image.getUserId())){
                return false;
            }
        }
        if (criteria.getKeyword() != null && !criteria.getKeyword().trim().isEmpty()) {
            String keyword = criteria.getKeyword().toLowerCase();
            boolean keywordMatch = image.getName().toLowerCase().contains(keyword) ||
                                 (image.getDescription() != null && image.getDescription().toLowerCase().contains(keyword)) ||
                                 (image.getTags() != null && image.getTags().toLowerCase().contains(keyword));
            if (!keywordMatch) return false;
        }
        
        // 标签匹配
        if (criteria.getTags() != null && !criteria.getTags().isEmpty()) {
            List<String> imageTags = imageTagRepository.findTagNamesByImageId(image.getId());
            boolean tagMatch = criteria.getTags().stream().anyMatch(imageTags::contains);
            if (!tagMatch) return false;
        }
        
        // 文件类型匹配
        if (criteria.getMimeTypes() != null && !criteria.getMimeTypes().isEmpty()) {
            if (!criteria.getMimeTypes().contains(image.getMimeType())) return false;
        }
        
        // 尺寸范围匹配
        if (criteria.getMinWidth() != null && image.getWidth() < criteria.getMinWidth()) return false;
        if (criteria.getMaxWidth() != null && image.getWidth() > criteria.getMaxWidth()) return false;
        if (criteria.getMinHeight() != null && image.getHeight() < criteria.getMinHeight()) return false;
        if (criteria.getMaxHeight() != null && image.getHeight() > criteria.getMaxHeight()) return false;
        
        // 文件大小范围匹配
        if (criteria.getMinFileSize() != null && image.getFileSize() < criteria.getMinFileSize()) return false;
        if (criteria.getMaxFileSize() != null && image.getFileSize() > criteria.getMaxFileSize()) return false;
        
        // 时间范围匹配
        if (criteria.getStartDate() != null && image.getCreatedAt().isBefore(criteria.getStartDate())) return false;
        if (criteria.getEndDate() != null && image.getCreatedAt().isAfter(criteria.getEndDate())) return false;

        return true;
    }
    
    /**
     * 排序图片
     */
    private List<Image> sortImages(List<Image> images, String sortBy, String sortDir) {
        Comparator<Image> comparator;
        
        switch (sortBy) {
            case "name":
                comparator = Comparator.comparing(Image::getName);
                break;
            case "fileSize":
                comparator = Comparator.comparing(Image::getFileSize);
                break;
            case "usageCount":
                comparator = Comparator.comparing(Image::getUsageCount);
                break;
            case "updatedAt":
                comparator = Comparator.comparing(Image::getUpdatedAt);
                break;
            default:
                comparator = Comparator.comparing(Image::getCreatedAt);
        }
        
        if ("desc".equalsIgnoreCase(sortDir)) {
            comparator = comparator.reversed();
        }
        
        return images.stream().sorted(comparator).collect(Collectors.toList());
    }
    
    /**
     * 计算标签权重
     */
    private int calculateTagWeight(long usageCount, long minUsage, long maxUsage) {
        if (maxUsage == minUsage) return 3;
        
        double ratio = (double) (usageCount - minUsage) / (maxUsage - minUsage);
        
        if (ratio >= 0.8) return 5;
        if (ratio >= 0.6) return 4;
        if (ratio >= 0.4) return 3;
        if (ratio >= 0.2) return 2;
        return 1;
    }
    
    /**
     * 转换为ImageDTO
     */
    private ImageDTO convertToImageDTO(Image image) {
        return imageService.getImageById(image.getId()).orElse(null);
    }
    
    /**
     * 转换为TagDTO
     */
    private TagDTO convertToTagDTO(Tag tag) {
        TagDTO dto = new TagDTO();
        dto.setId(tag.getId());
        dto.setName(tag.getName());
        dto.setCategory(tag.getCategory());
        dto.setUsageCount(tag.getUsageCount());
        dto.setCreatedAt(tag.getCreatedAt());
        dto.setUpdatedAt(tag.getUpdatedAt());
        return dto;
    }
    
    /**
     * 搜索条件类
     */
    public static class SearchCriteria {
        private String keyword;
        private List<String> tags;
        private List<String> mimeTypes;
        private Integer minWidth;
        private Integer maxWidth;
        private Integer minHeight;
        private Integer maxHeight;
        private Long minFileSize;
        private Long maxFileSize;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private java.time.LocalDateTime startDate;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private java.time.LocalDateTime endDate;
        private int page = 0;
        private int size = 20;
        private String sortBy = "createdAt";
        private String sortDir = "desc";
        private Long userId;
        
        // Getters and Setters
        public String getKeyword() { return keyword; }
        public void setKeyword(String keyword) { this.keyword = keyword; }
        
        public List<String> getTags() { return tags; }
        public void setTags(List<String> tags) { this.tags = tags; }
        
        public List<String> getMimeTypes() { return mimeTypes; }
        public void setMimeTypes(List<String> mimeTypes) { this.mimeTypes = mimeTypes; }
        
        public Integer getMinWidth() { return minWidth; }
        public void setMinWidth(Integer minWidth) { this.minWidth = minWidth; }
        
        public Integer getMaxWidth() { return maxWidth; }
        public void setMaxWidth(Integer maxWidth) { this.maxWidth = maxWidth; }
        
        public Integer getMinHeight() { return minHeight; }
        public void setMinHeight(Integer minHeight) { this.minHeight = minHeight; }
        
        public Integer getMaxHeight() { return maxHeight; }
        public void setMaxHeight(Integer maxHeight) { this.maxHeight = maxHeight; }
        
        public Long getMinFileSize() { return minFileSize; }
        public void setMinFileSize(Long minFileSize) { this.minFileSize = minFileSize; }
        
        public Long getMaxFileSize() { return maxFileSize; }
        public void setMaxFileSize(Long maxFileSize) { this.maxFileSize = maxFileSize; }
        
        public java.time.LocalDateTime getStartDate() { return startDate; }
        public void setStartDate(java.time.LocalDateTime startDate) { this.startDate = startDate; }
        
        public java.time.LocalDateTime getEndDate() { return endDate; }
        public void setEndDate(java.time.LocalDateTime endDate) { this.endDate = endDate; }
        
        public int getPage() { return page; }
        public void setPage(int page) { this.page = page; }
        
        public int getSize() { return size; }
        public void setSize(int size) { this.size = size; }
        
        public String getSortBy() { return sortBy; }
        public void setSortBy(String sortBy) { this.sortBy = sortBy; }
        
        public String getSortDir() { return sortDir; }
        public void setSortDir(String sortDir) { this.sortDir = sortDir; }

        public Long getUserId() { return userId; }
        public void setUserId(Long userId) { this.userId = userId; }

        @Override
        public String toString() {
            return "SearchCriteria{" +
                    "keyword='" + keyword + '\'' +
                    ", tags=" + tags +
                    ", mimeTypes=" + mimeTypes +
                    ", minWidth=" + minWidth +
                    ", maxWidth=" + maxWidth +
                    ", minHeight=" + minHeight +
                    ", maxHeight=" + maxHeight +
                    ", minFileSize=" + minFileSize +
                    ", maxFileSize=" + maxFileSize +
                    ", startDate=" + startDate +
                    ", endDate=" + endDate +
                    ", page=" + page +
                    ", size=" + size +
                    ", sortBy='" + sortBy + '\'' +
                    ", sortDir='" + sortDir + '\'' +
                    ", userId=" + userId +
                    '}';
        }
    }
    
    /**
     * 标签统计信息
     */
    public static class TagStatistics {
        private String tagName;
        private long usageCount;
        
        // Getters and Setters
        public String getTagName() { return tagName; }
        public void setTagName(String tagName) { this.tagName = tagName; }
        
        public long getUsageCount() { return usageCount; }
        public void setUsageCount(long usageCount) { this.usageCount = usageCount; }
    }
    
    /**
     * 标签云项目
     */
    public static class TagCloudItem {
        private String tagName;
        private long usageCount;
        private int weight; // 1-5级权重
        
        // Getters and Setters
        public String getTagName() { return tagName; }
        public void setTagName(String tagName) { this.tagName = tagName; }
        
        public long getUsageCount() { return usageCount; }
        public void setUsageCount(long usageCount) { this.usageCount = usageCount; }
        
        public int getWeight() { return weight; }
        public void setWeight(int weight) { this.weight = weight; }
    }
    
    /**
     * 综合模糊搜索（同时搜索图片名称和标签名称）
     */
    public Page<ImageDTO> fuzzySearch(String keyword, int page, int size, String sortBy, String sortDir) {
        log.info("Fuzzy search for keyword: {}", keyword);
        
        if (keyword == null || keyword.trim().isEmpty()) {
            return Page.empty();
        }

        // 1. 搜索图片名称匹配
        List<Image> images=imageRepository.findByKeyword(keyword,null).stream()
                .filter(image -> !image.getIsDeleted())
                .collect(Collectors.toList());
        // 排序
        images = sortImages(images, sortBy, sortDir);
        
        // 分页
        Pageable pageable = PageRequest.of(page, size);
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), images.size());
        
        if (start >= images.size()) {
            return Page.empty(pageable);
        }
        
        List<Image> pageContent = images.subList(start, end);
        List<ImageDTO> imageDTOs = pageContent.stream()
                .map(this::convertToImageDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(imageDTOs, pageable, images.size());
    }
    
    /**
     * 根据标签名称模糊搜索图片
     */
    public Page<ImageDTO> searchByTagName(String tagName, int page, int size, String sortBy, String sortDir) {
        log.info("Searching images by tag name: {}", tagName);
        
        if (tagName == null || tagName.trim().isEmpty()) {
            return Page.empty();
        }
        
        String normalizedTagName = tagName.trim().toLowerCase();
        
        // 查找匹配的标签（模糊匹配）
        List<Tag> matchingTags = tagRepository.findAll().stream()
                .filter(tag -> !tag.getIsDeleted())
                .filter(tag -> tag.getName().toLowerCase().contains(normalizedTagName))
                .collect(Collectors.toList());
        
        if (matchingTags.isEmpty()) {
            return Page.empty();
        }
        
        // 获取所有匹配标签的图片ID
        Set<Long> imageIds = new HashSet<>();
        for (Tag tag : matchingTags) {
            List<Long> tagImageIds = imageTagRepository.findImageIdsByTagName(tag.getName());
            imageIds.addAll(tagImageIds);
        }
        
        if (imageIds.isEmpty()) {
            return Page.empty();
        }
        
        // 获取图片并过滤
        List<Image> images = imageRepository.findAllById(imageIds)
                .stream()
                .filter(image -> !image.getIsDeleted())
                .collect(Collectors.toList());
        
        // 排序
        images = sortImages(images, sortBy, sortDir);
        
        // 分页
        Pageable pageable = PageRequest.of(page, size);
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), images.size());
        
        if (start >= images.size()) {
            return Page.empty(pageable);
        }
        
        List<Image> pageContent = images.subList(start, end);
        List<ImageDTO> imageDTOs = pageContent.stream()
                .map(this::convertToImageDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(imageDTOs, pageable, images.size());
    }
    
    /**
     * 智能关键词搜索结果
     */
    public SearchResult smartKeywordSearch(String keyword, int page, int size, String sortBy, String sortDir) {
        log.info("Smart keyword search: {}", keyword);
        
        if (keyword == null || keyword.trim().isEmpty()) {
            return createEmptySearchResult("请输入搜索关键词");
        }
        
        String normalizedKeyword = keyword.trim().toLowerCase();
        
        // 执行智能搜索
        Page<ImageDTO> imagePage = intelligentKeywordSearch(keyword, page, size, sortBy, sortDir);
        
        // 创建搜索结果
        SearchResult result = new SearchResult();
        result.setSuccess(true);
        result.setKeyword(keyword);
        result.setNormalizedKeyword(normalizedKeyword);
        result.setImages(imagePage.getContent());
        result.setTotalResults(imagePage.getTotalElements());
        result.setCurrentPage(imagePage.getNumber());
        result.setTotalPages(imagePage.getTotalPages());
        result.setPageSize(imagePage.getSize());
        result.setHasNext(imagePage.hasNext());
        result.setHasPrevious(imagePage.hasPrevious());
        
        // 添加搜索建议
        if (imagePage.getTotalElements() == 0) {
            result.setSuggestions(getSearchSuggestions(normalizedKeyword, 5));
            result.setMessage("未找到相关图片，您可以尝试以下搜索建议");
        } else {
            result.setMessage(String.format("找到 %d 个相关结果", imagePage.getTotalElements()));
        }
        
        return result;
    }
    
    /**
     * 创建空搜索结果
     */
    private SearchResult createEmptySearchResult(String message) {
        SearchResult result = new SearchResult();
        result.setSuccess(false);
        result.setMessage(message);
        result.setImages(new ArrayList<>());
        result.setTotalResults(0L);
        result.setCurrentPage(0);
        result.setTotalPages(0);
        result.setPageSize(0);
        result.setHasNext(false);
        result.setHasPrevious(false);
        return result;
    }
    
    /**
     * 搜索结果类
     */
    public static class SearchResult {
        private boolean success;
        private String message;
        private String keyword;
        private String normalizedKeyword;
        private List<ImageDTO> images;
        private long totalResults;
        private int currentPage;
        private int totalPages;
        private int pageSize;
        private boolean hasNext;
        private boolean hasPrevious;
        private List<SearchSuggestion> suggestions;
        private Image image; // 单个图片结果
        private double relevanceScore; // 相关性评分
        private List<String> highlights; // 高亮信息
        
        // Getters and Setters
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        
        public String getKeyword() { return keyword; }
        public void setKeyword(String keyword) { this.keyword = keyword; }
        
        public String getNormalizedKeyword() { return normalizedKeyword; }
        public void setNormalizedKeyword(String normalizedKeyword) { this.normalizedKeyword = normalizedKeyword; }
        
        public List<ImageDTO> getImages() { return images; }
        public void setImages(List<ImageDTO> images) { this.images = images; }
        
        public long getTotalResults() { return totalResults; }
        public void setTotalResults(long totalResults) { this.totalResults = totalResults; }
        
        public int getCurrentPage() { return currentPage; }
        public void setCurrentPage(int currentPage) { this.currentPage = currentPage; }
        
        public int getTotalPages() { return totalPages; }
        public void setTotalPages(int totalPages) { this.totalPages = totalPages; }
        
        public int getPageSize() { return pageSize; }
        public void setPageSize(int pageSize) { this.pageSize = pageSize; }
        
        public boolean isHasNext() { return hasNext; }
        public void setHasNext(boolean hasNext) { this.hasNext = hasNext; }
        
        public boolean isHasPrevious() { return hasPrevious; }
        public void setHasPrevious(boolean hasPrevious) { this.hasPrevious = hasPrevious; }
        
        public List<SearchSuggestion> getSuggestions() { return suggestions; }
        public void setSuggestions(List<SearchSuggestion> suggestions) { this.suggestions = suggestions; }
        
        public Image getImage() { return image; }
        public void setImage(Image image) { this.image = image; }
        
        public double getRelevanceScore() { return relevanceScore; }
        public void setRelevanceScore(double relevanceScore) { this.relevanceScore = relevanceScore; }
        
        public List<String> getHighlights() { return highlights; }
        public void setHighlights(List<String> highlights) { this.highlights = highlights; }
    }
    
    /**
     * 搜索建议
     */
    public static class SearchSuggestion {
        private String text;
        private String type; // "tag" or "image"
        private int usageCount;
        
        // Getters and Setters
        public String getText() { return text; }
        public void setText(String text) { this.text = text; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public int getUsageCount() { return usageCount; }
        public void setUsageCount(int usageCount) { this.usageCount = usageCount; }
    }
}